home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 #1 / Ham Radio 2000.iso / ham2000 / tcp_ip / wnos / wn941101 / timer.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-10  |  5.9 KB  |  264 lines

  1. #include <stdio.h>
  2. #include "global.h"
  3. #include "timer.h"
  4. #include "proc.h"
  5. #include "mbuf.h"
  6. #include "commands.h"
  7. #include "daemon.h"
  8. #include "hardware.h"
  9. #include "socket.h"
  10.  
  11. /* Head of running timer chain.
  12.  * The list of running timers is sorted in increasing order of expiration;
  13.  * i.e., the first timer to expire is always at the head of the list.
  14.  */
  15. #ifdef MDEBUG
  16. struct timer *Timers;        /* also used in alloc.c */
  17. #else
  18. static struct timer *Timers;
  19. #endif
  20.  
  21. static void t_alarm __ARGS((void *x));
  22.  
  23. /* Process that handles clock ticks */
  24. void
  25. timerproc(int i,void *v1,void *v2)
  26. {
  27.     struct timer *t, *p, *expired;
  28.     int i_state;
  29.     void (**vf)();
  30.  
  31.     for(;;){
  32.         i_state = dirps();        /* Tick is modified by an interrupt */
  33.  
  34.         while(Tick == 0)
  35.             pwait(&Tick);
  36.  
  37.         Tick = 0;                /* */
  38.  
  39.         restore(i_state);
  40.  
  41.         if(!istate()) {
  42.             restore(1);
  43.             tputs("\ntimer: ints were off\n\n");
  44.             usflush(Current->output);        /* make sure it gets out */
  45.         }
  46.  
  47.         if(!uploadstatus)        /* TEST */
  48.             /* Call the functions listed in config.c */
  49.             for(vf = Cfunc;*vf != NULL;vf++)
  50.                 (*vf)();
  51.  
  52.         usflush(Current->output);        /* Flush current session output */
  53.         pwait(NULL);                    /* Let them all do their writes */
  54.         flushall();                        /* And flush out stdout too */
  55.  
  56.         if(Timers == NULLTIMER)
  57.             continue;            /* No active timers, all done */
  58.  
  59.         /* Initialize null expired timer list */
  60.         expired = NULLTIMER;
  61.  
  62.         /* Move expired timers to expired list. Note use of
  63.          * subtraction and comparison to zero rather than the
  64.          * more obvious simple comparison; this avoids
  65.          * problems when the clock count wraps around.
  66.          */
  67.         while(Timers != NULLTIMER && (Clock - Timers->expiration) >= 0){
  68.             if(Timers->next == Timers) {
  69.                 printf("\nTimer loop at %lx\n\n",(long)Timers);
  70.                 iostop();
  71.                 exit(251);
  72.             }
  73.             /* Save Timers since stop_timer will change it */
  74.             t = Timers;
  75.             stop_timer(t);
  76.  
  77.             /* Add to expired timer list */
  78.             if(expired == NULLTIMER){
  79.                 expired = t;
  80.             } else {
  81.                 for(p = expired ; p->next != NULLTIMER ; p = p->next);
  82.                 p->next = t;    /* place at end of chain */
  83.             }
  84.             t->next = NULLTIMER;
  85.         }
  86.         /* Now go through the list of expired timers, removing each
  87.          * one and kicking the notify function, if there is one
  88.          * Note that the state should ne TIMER_STOP. We just stopped
  89.          * it remember? Now is someone else changed it, ignore timer.
  90.          */
  91.         while((t = expired) != NULLTIMER){
  92.             expired = t->next;
  93.             if(t->state == TIMER_STOP) {
  94.                 t->state = TIMER_EXPIRE;
  95.                 if(t->func)
  96.                     (*t->func)(t->arg);
  97.             }
  98.         }
  99.         pwait(NULL);    /* Let them run before handling more ticks */
  100.     }
  101. }
  102.  
  103. /* Start a timer */
  104. void
  105. start_timer(struct timer *t)
  106. {
  107.     struct timer *tnext, *tprev = NULLTIMER;
  108.  
  109.     if(t == NULLTIMER)
  110.         return;
  111.  
  112.     if(t->state == TIMER_RUN)
  113.         stop_timer(t);
  114.  
  115.     if(t->duration == 0)
  116.         return;        /* A duration value of 0 disables the timer */
  117.  
  118.     t->expiration = Clock + t->duration;
  119.     t->state = TIMER_RUN;
  120.  
  121.     /* Find right place on list for this guy. Once again, note use
  122.      * of subtraction and comparison with zero rather than direct
  123.      * comparison of expiration times.
  124.      */
  125.     for(tnext = Timers; tnext != NULLTIMER; tprev = tnext, tnext = tnext->next) {
  126.         if((tnext->expiration - t->expiration) >= 0)
  127.             break;
  128.     }
  129.     /* At this point, tprev points to the entry that should go right
  130.      * before us, and tnext points to the entry just after us. Either or
  131.      * both may be null.
  132.      */
  133.     if(tprev == NULLTIMER)
  134.         Timers = t;        /* Put at beginning */
  135.     else
  136.         tprev->next = t;
  137.  
  138.     t->next = tnext;
  139. }
  140.  
  141. /* Stop a timer */
  142. void
  143. stop_timer(struct timer *timer)
  144. {
  145.     struct timer *t, *tlast = NULLTIMER;
  146.  
  147.     if(timer == NULLTIMER || timer->state != TIMER_RUN)
  148.         return;
  149.  
  150.     /* Verify that timer is really on list */
  151.     for(t = Timers; t != NULLTIMER; tlast = t, t = t->next)
  152.         if(t == timer)
  153.             break;
  154.  
  155.     if(t == NULLTIMER)
  156.         return;        /* Should probably panic here */
  157.  
  158.     /* Delete from active timer list */
  159.     if(tlast != NULLTIMER)
  160.         tlast->next = t->next;
  161.     else
  162.         Timers = t->next;    /* Was first on list */
  163.  
  164.     t->state = TIMER_STOP;
  165. }
  166.  
  167. /* Return millisecs remaining on this timer */
  168. int32
  169. read_timer(struct timer *t)
  170. {
  171.     int32 remaining;
  172.  
  173.     if(t == NULLTIMER || t->state != TIMER_RUN)
  174.         remaining = 0;
  175.     else
  176.         remaining = t->expiration - Clock;
  177.  
  178.     return (remaining <= 0) ? 0 : (remaining * MSPTICK);
  179. }
  180.  
  181. void
  182. set_timer(struct timer *t,int32 interval)
  183. {
  184.     if(t == NULLTIMER)
  185.         return;
  186.  
  187.     /* Round up small nonzero intervals to one tick */
  188.     t->duration = (interval != 0) ? 1 + (interval + MSPTICK - 1) / MSPTICK : 0;
  189. }
  190.  
  191. /* Delay process for specified number of millisecs
  192.  * normally returns 0, if aborted by alarm returning -1 */
  193. int
  194. pause(int32 ms)
  195. {
  196.     int val;
  197.  
  198.     if(Curproc == NULLPROC || ms == 0)
  199.         return 0;
  200.  
  201.     alarm(ms);
  202.  
  203.     /* The actual event doesn't matter, since we'll be alerted */
  204.     while(Curproc->alarm.state == TIMER_RUN) {
  205.         if((val = (int)pwait(Curproc)) != 0)
  206.             break;
  207.     }
  208.     alarm(0L); /* Make sure it's stopped, in case we were killed */
  209.  
  210.     return (val == EALARM) ? 0 : -1;
  211. }
  212.  
  213. static void
  214. t_alarm(void *x)
  215. {
  216.     alert((struct proc *)x,(void *)EALARM);
  217. }
  218.  
  219. /* Send signal to current process after specified number of millisecs */
  220. void
  221. alarm(int32 ms)
  222. {
  223.     if(Curproc != NULLPROC) {
  224.         set_timer(&Curproc->alarm,ms);
  225.         Curproc->alarm.func = t_alarm;
  226.         Curproc->alarm.arg = (char *)Curproc;
  227.         start_timer(&Curproc->alarm);
  228.     }
  229. }
  230.  
  231. /* Convert time count in seconds to printable days:hr:min:sec format */
  232. char *
  233. tformat(int32 t)
  234. {
  235.     static char buf[20], *cp;
  236.     unsigned int days, hrs, mins, secs;
  237.     int minus;
  238.  
  239.     if(t < 0) {
  240.         t = -t;
  241.         minus = 1;
  242.     } else
  243.         minus = 0;
  244.  
  245.     secs = (int)(t % 60);
  246.     t /= 60;
  247.     mins = (int)(t % 60);
  248.     t /= 60;
  249.     hrs = (int)(t % 24);
  250.     t /= 24;
  251.     days = (int)(t);
  252.  
  253.     if(minus) {
  254.         cp = buf + 1;
  255.         buf[0] = '-';
  256.     } else
  257.         cp = buf;
  258.  
  259.     sprintf(cp,"%ud:%02uh:%02um:%02us",days,hrs,mins,secs);
  260.  
  261.     return buf;
  262. }
  263.  
  264.